import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;

public class BankTest {

    public static void main(String[] args) {
        Bank bank = new Bank();
        Inventory inventory = new Inventory();
        int cost = 10;
        int id = 35;
        CompletableFuture<Boolean> task = bank.decrement(cost)
                .thenCompose((ok) -> {
                    if (!ok) {
                        return CompletableFuture.completedFuture(false);
                    }
                    return inventory.giveItem(id)
                            .thenApply(giveOk -> true)
                            .exceptionally(e -> {
                                System.out.println("异常: " + e);
                                bank.refund(cost);
                                return false;
                            });

                });
        try {
            System.out.println(task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    static class Bank {
        CompletableFuture<Boolean> decrement(int cost) {
            try {
                Thread.sleep(cost * 100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (cost > 5) {
                System.out.println(Thread.currentThread().getName() + "  扣钱成功, 数量： " + cost);
                return CompletableFuture.completedFuture(true);
            } else {
                System.out.println(Thread.currentThread().getName() + "  扣钱失败, 数量： " + cost);
                return CompletableFuture.completedFuture(false);
            }
        }

        CompletableFuture<Boolean> refund(int cost) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "  还钱成功, 数量： " + cost);
            return CompletableFuture.completedFuture(true);
        }
    }

    static class Inventory {
        CompletableFuture<Boolean> giveItem(int id) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (id < 5) {
                System.out.println(Thread.currentThread().getName() + "  发货 OK, id： " + id);
                return CompletableFuture.completedFuture(true);
            } else {
                throw new CompletionException(new RuntimeException("商品 id 错误"));
            }
        }
    }
}
